<?php
/**
 * File: db_mysql.class.php
 * Author: apple
 * Update: 2009-9-22 13:35:18
*/

if(!defined('IN_SITE')) {
	exit('Access Denied');
}

class db_mysql {

	var $version = '';
	var $querynum = 0;
	var $link = null;

	function connect($dbhost, $dbuser, $dbpw, $dbname = '', $pconnect = 0, $halt = TRUE, $dbcharset2 = '') {
		$func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
		if(!$this->link = @$func($dbhost, $dbuser, $dbpw, 1)) {
			$halt && $this->halt();
		} else {
			if($this->version() > '4.1') {
				global $charset, $dbcharset;
				$dbcharset = $dbcharset2 ? $dbcharset2 : $dbcharset;
				$dbcharset = !$dbcharset && in_array(strtolower($charset), array('gbk', 'big5', 'utf-8')) ? str_replace('-', '', $charset) : $dbcharset;
				$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
				$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
				$serverset && mysql_query("SET $serverset", $this->link);
			}
			$dbname && @mysql_select_db($dbname, $this->link);
		}
	}

	function select_db($dbname) {
		return mysql_select_db($dbname, $this->link);
	}

	function fetch_array($query, $result_type = MYSQL_ASSOC) {
		return mysql_fetch_array($query, $result_type);
	}

	function fetch_first($sql) {
		return $this->fetch_array($this->query($sql));
	}
	
	function fetch_all($sql, $id = '') {
		$arr = array();
		$query = $this->query($sql);
		while($data = $this->fetch_array($query)) {
			$id ? $arr[$data[$id]] = $data : $arr[] = $data;
		}
		return $arr;
	}

	function result_first($sql) {
		return $this->result($this->query($sql), 0);
	}

	function query($sql, $type = '') {
		global $start_time, $sqldebug, $sqlspenttimes;
		
		if(defined('SYS_DEBUG') && SYS_DEBUG) {
			@include_once SITE_ROOT.'include/debug.func.php';
			sqldebug($sql);
		}
		
		$func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
			'mysql_unbuffered_query' : 'mysql_query';
		if(!($query = $func($sql, $this->link))) {
			if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
				$this->close();
				require SITE_ROOT.'config.inc.php';
				$this->connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect, true, $dbcharset);
				$this->query($sql, 'RETRY'.$type);
			} elseif($type != 'SILENT' && substr($type, 5) != 'SILENT') {
				$this->halt('MySQL Query Error', $sql);
			}
		}

		$this->querynum++;
		return $query;
	}

	//返回 INSERT，UPDATE，DELETE 操作查询结果的条数
	function affected_rows() {
		return mysql_affected_rows($this->link);
	}

	//返回 MySQL 操作产生的文本错误信息
	function error() {
		return (($this->link) ? mysql_error($this->link) : mysql_error());
	}

	//返回 MySQL 操作中的错误信息的数字编码
	function errno() {
		return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());
	}

	function result($query, $row = 0) {
		$query = @mysql_result($query, $row);
		return $query;
	}

	//取得select语句查询结果的数目
	function num_rows($query) {
		$query = mysql_num_rows($query);
		return $query;
	}

	//取得结果集中字段的数目
	function num_fields($query) {
		return mysql_num_fields($query);
	}

	//释放资源
	function free_result($query) {
		return mysql_free_result($query);
	}

	//取得上一步 INSERT 操作产生的记录ID
	function insert_id() {
		return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
	}
	
	function insert($tablename, $array)
	{
		if(defined('SYS_DEBUG') && SYS_DEBUG)
		{
			$this->check_fields($tablename, $array);
		}
		return $this->query("INSERT INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')");
	}
	
	function update($tablename, $array, $where = '')
	{
		if(defined('SYS_DEBUG') && SYS_DEBUG)
		{
			$this->check_fields($tablename, $array);
		}
		$sql = '';
		foreach($array as $k=>$v)
		{
			$sql .= ", `$k`='$v'";
		}
		$sql = substr($sql, 1);
		$sql = "UPDATE `$tablename` SET $sql";
		if($where)
		{
			$sql .= " WHERE $where";
		}

		return $this->query($sql);
	}
	
	function replace($tablename, $array)
	{
		if(defined('SYS_DEBUG') && SYS_DEBUG)
		{
			$this->check_fields($tablename, $array);
		}
		return $this->query("REPLACE INTO `$tablename`(`".implode('`,`', array_keys($array))."`) VALUES('".implode("','", $array)."')");
	}
	
	function get_primary($table)
	{
		$result = $this->query("SHOW COLUMNS FROM $table");
		while($r = $this->fetch_array($result))
		{
			if($r['Key'] == 'PRI') break;
		}
		$this->free_result($result);
		return $r['Field'];
	}

	function check_fields($tablename, $array)
	{
		$fields = $this->get_fields($tablename);
		foreach($array AS $k=>$v)
		{
			if(!in_array($k,$fields))
			{
				$this->halt('MySQL Query Error', "Unknown column '$k' in field list");
				return false;
			}
		}
	}
	
	function get_fields($table)
	{
		$fields = array();
		$result = $this->query("SHOW COLUMNS FROM $table");
		while($r = $this->fetch_array($result))
		{
			$fields[] = $r['Field'];
		}
		$this->free_result($result);
		return $fields;
	}

	//取得数字数据集
	function fetch_row($query) {
		$query = mysql_fetch_row($query);
		return $query;
	}

	function fetch_fields($query) {
		return mysql_fetch_field($query);
	}

	function version() {
		if(empty($this->version)) {
			$this->version = mysql_get_server_info($this->link);
		}
		return $this->version;
	}

	function close() {
		return mysql_close($this->link);
	}

	//抛出错误提示
	function halt($sql = '') {
		$this->dberrortolog($sql);
		if(defined('SYS_DEBUG') && SYS_DEBUG) {
			$this->debugcodetolog($sql);
		}
		if($GLOBALS['dbreport'] && $GLOBALS['adminemail']) {
			echo "<br /><br />An error report email has been dispatched to our administrator.";
			@sendmail($GLOBALS['adminemail'], 'Warning! Gemini Project MySQL Error Report',
				"There seems to have been a problem with the database of the gemini project.\n\n".
				strip_tags($this->throwtips($sql))."\n\n".
				"Please check-up your MySQL server and Program scripts, similar errors will not be reported again in recent 24 hours\n");
		}
		$this->throwtips($sql);
	}
	
	function debugcodetolog($sql = '') {
		global $timestamp, $BASESCRIPT;
		$currentdate = date('Y-m-d', $timestamp);
		$path = SITE_ROOT.'data/log/debug.'.$currentdate.'.log.php';
		if(!file_exists($path)) {
			$content = "<?php exit(\"Access Denied!\");?>\r\n";
		} else {
			$content = "";
		}
		$content.= "\r\nError:".$this->error();
		$content.="\r\nMySQL Num:".$this->errno();
		$content.="\r\nScript:".$BASESCRIPT;
		$content.="\r\nTime:".date('Y-m-d H:i:s', $timestamp);
		$content.="\r\n----------------------------------------------------------";
		$this->errortolog($content, $path);
	}

	function dberrortolog($sql = '') {
		global  $timestamp, $BASESCRIPT;
		$path = SITE_ROOT.'data/log/dberror.log.php';
		if(!file_exists($path)) {
			$content = "<?php exit(\"Access Denied!\");?>\r\n";
		} else {
			$content = "";
		}
		$content.= $BASESCRIPT.'|'.$sql.'|'.$this->errno().'|'.$this->error().'|'.$timestamp."\r\n";  //角本文件|SQL语句|错误编号|错误信息|产生时间
		$this->errortolog($content, $path);
	}

	function errortolog($content, $path) {
		error_log($content, 3, $path);
		chmod($path, 0777);
	}
	
	function throwtips($sql) {
		global $timestamp, $BASESCRIPT;
		require_once SITE_ROOT.'include/db_mysql_errno.inc.php';
		$msg = $db_msg['errno_'.$this->errno()];
		if (!$msg)
		{
			$msg = $db_msg['unknow'];
		}
		$message = "<html>\n<head>\n";
		$message .= "<meta content=\"text/html; charset=gbk\" http-equiv=\"Content-Type\">\n";
		$message .= "</head>\n";
		$message .= "<body>\n";
		$message .= "<p style=\"font-family: Verdana, Tahoma; font-size: 11px; background:#FFF;\">\n";
		$message .= "---------- The WebSite's Tips Info ----------<br />\n";
		$message .= "<strong>Error Info: </strong>" . $msg . "<br />\n";
		$message .= "<strong>Time: </strong>" .date('Y-m-d H:i:s', $timestamp) . "<br />\n";
		if(defined('SYS_DEBUG') && SYS_DEBUG){
			$message .= "<strong>Script: </strong>" .$BASESCRIPT. "<br />\n";
			if ($sql) {
				$message .= "<strong>SQL: </strong><code>" . htmlspecialchars($sql) . "</code><br />\n";
			}
			$message .= "<strong>MySQL Error: </strong>" . $this->error() . "<br />\n";
			$message .= "<strong>Error Num: </strong>" . $this->errno() . "\n";
		}
		$message .= "</p>\n";
		$message .= "</body>\n</html>";
		echo str_replace($GLOBALS['tablepre'], '[Table]', $message);
		exit;
	 }
}
?>